from loa_game import WHITE, BLACK, EMPTY, MoveAction, SpinAction

Q0 = 0
Q1 = 1
Q2 = 2
Q3 = 3
Q4 = 4
Qd = 'qd'

DIR_ROW = 0
DIR_COL = 1
quadVertices = {Q0: 0, Q1:1, Q2:1, Q3:1, Q4:1, Qd:1}
quadThickLines = {Q0:0, Q1:2, Q2:3, Q3:4, Q4:4, Qd:4}
quadFilledRegions = {Q0:0, Q1:1, Q2:2, Q3:3, Q4:4, Qd:2}
#quadDict = {(EMPTY,EMPTY,EMPTY,EMPTY):((BLACK, Q1),(WHITE, Q1)),
#            (EMPTY,)}


def identifyQuad(lu, ru, ld, rd, color):
    numOc = [lu, ru, ld, rd].count(color)
    if numOc == 0:
        return Q0
    if numOc == 1:
        return Q1
    if numOc == 2:
        if lu == rd or ld == ru:
            return Qd
        else:
            return Q2
    if numOc == 3:
        return Q3
    if numOc == 4:
        return Q4

def getQuadFromSquare(square,color):
    return identifyQuad(square[0],square[1],square[2],square[3],color)

def countColors(cells):
    w,b,e = 0,0,0
    for i in range(0, len(cells)):
        if cells[i] == WHITE:
            w = w + 1
        elif cells[i] == BLACK:
            b = b + 1
        else:
            e = e + 1
    return {WHITE:w, BLACK:b, EMPTY:e}

def countQuads(squareList,color):
    q0,q1,q2,q3,q4,qd = 0,0,0,0,0,0
    for i in range(0,len(squareList)):
        q = getQuadFromSquare(squareList[i], color)
        if q == Q0:
            q0 = q0 + 1    
        elif q == Q1:
            q1 = q1 + 1
        elif q == Q2:
            q2 = q2 + 1
        elif q == Q3:
            q3 = q3 + 1
        elif q == Q4:
            q4 = q4 + 1
        elif q == Qd:
            qd = qd + 1
    return q0,q1,q2,q3,q4,qd

#   returns the value for the specified cell
#   if the cell is located outside the board, empty is returned
def getCell(board,i,j,vetoDict = {}):
        if i == -1 or j == -1:
            return EMPTY
        elif i >= len(board) or j >= len(board):
            return EMPTY
        else:
            return vetoDict.get((i,j),board[i][j])


#   returns a tuple of cells in a square of 2x2 described by the upper left corner 
#    def color - default color for cell i,j
def getSquare(board,i,j, vetoDict={}):
    return (getCell(board,i, j,vetoDict), getCell(board,i, j+1,vetoDict),
            getCell(board,i+1, j,vetoDict), getCell(board,i+1, j+1,vetoDict))



#   returns list of all the squares that interact with
#   the specified cell
#   defColor - default color for specified cell
def getCellSquares(board, cellRow,cellCol, vetoDict={}):
        squares = []
        for i in range(cellRow-1, cellRow+1):
            for j in range(cellCol-1, cellCol+1):
                squares.append(getSquare(board,i, j,vetoDict)) 
        return squares

#   returns squares intersecting with the specified square    
def getSquareNeighbourSquares(board,cellRow,cellCol,vetoDict={}):
    squares = []
    for i in range(cellRow-1, cellRow+2):
        for j in range(cellCol-1, cellCol+2):
            if i == cellRow and j == cellCol:
                continue
            sqr = getSquare(board,i, j,vetoDict)
            squares.append(sqr)
    return squares

class QuadState():
    
    def __init__(self, gameState):
        self.board = gameState.board
        self.quadsDicts = {WHITE:{}, BLACK:{}}
        self.nWhites = gameState.whites
        self.nBlacks = gameState.blacks
        self.countQuads()
            

        
    def countQuads(self):
        w0, w1, w2, w3, w4, wd = 0,0,0,0,0,0
        b0, b1, b2, b3, b4, bd = 0,0,0,0,0,0
        bLength = len(self.board)
        for i in range(-1, bLength):
            upLine, downLine = None, None
            if i > -1:    
                upLine = self.board[i]
            if i < bLength - 1:
                downLine = self.board[i+1]
            for j in range(-1, bLength):
                if i == -1:
                    if j == -1:
                        qw = identifyQuad(EMPTY, EMPTY, EMPTY, downLine[j+1], WHITE)
                        qb = identifyQuad(EMPTY, EMPTY, EMPTY, downLine[j+1], BLACK)
                    elif j == bLength - 1:
                        qw = identifyQuad(EMPTY, EMPTY, downLine[j], EMPTY, WHITE)
                        qb = identifyQuad(EMPTY, EMPTY, downLine[j], EMPTY, BLACK)
                    else:
                        qw = identifyQuad(EMPTY, EMPTY, downLine[j], downLine[j+1], WHITE)
                        qb = identifyQuad(EMPTY, EMPTY, downLine[j], downLine[j+1], BLACK)
                elif i == bLength - 1:
                    if j == -1:
                        qw = identifyQuad(EMPTY, upLine[j+1], EMPTY, EMPTY, WHITE)
                        qb = identifyQuad(EMPTY, upLine[j+1], EMPTY, EMPTY, BLACK)
                    elif j == bLength - 1:
                        qw = identifyQuad(upLine[j], EMPTY, EMPTY, EMPTY, WHITE)
                        qb = identifyQuad(upLine[j], EMPTY, EMPTY, EMPTY, BLACK)
                    else:
                        qw = identifyQuad(EMPTY, EMPTY, upLine[j], upLine[j+1], WHITE)
                        qb = identifyQuad(EMPTY, EMPTY, upLine[j], upLine[j+1], BLACK)
                else:
                    if j == -1:
                        qw = identifyQuad(EMPTY, upLine[j+1], EMPTY, downLine[j+1], WHITE)
                        qb = identifyQuad(EMPTY, upLine[j+1], EMPTY, downLine[j+1], BLACK)
                    elif j == bLength - 1:
                        qw = identifyQuad(upLine[j], EMPTY, downLine[j], EMPTY, WHITE)
                        qb = identifyQuad(upLine[j], EMPTY, downLine[j], EMPTY, BLACK)
                    else:
                        qw = identifyQuad(upLine[j], upLine[j+1], downLine[j], downLine[j+1], WHITE)
                        qb = identifyQuad(upLine[j], upLine[j+1], downLine[j], downLine[j+1], BLACK)
                
                if qw == Q1:
                    w1 = w1 + 1
                elif qw == Q2:
                    w2 = w2 + 1
                elif qw == Q3:
                    w3 = w3 + 1
                elif qw == Qd:
                    wd = wd + 1
                elif qw == Q4:
                    w4 = w4 + 1
                elif qw == Q0:
                    w0 = w0 + 1    
                    
                if qb == Q0:
                    b0 = b0 + 1    
                elif qb == Q1:
                    b1 = b1 + 1
                elif qb == Q2:
                    b2 = b2 + 1
                elif qb == Q3:
                    b3 = b3 + 1
                elif qb == Q3:
                    b4 = b4 + 1
                elif qb == Qd:
                    bd = bd + 1    
        self.quadsDicts[WHITE] = {Q0:w0, Q1:w1, Q2:w2, Q3:w3, Q4:w4, Qd:wd}
        self.quadsDicts[BLACK] = {Q0:b0, Q1:b1, Q2:b2, Q3:b3, Q4:b4, Qd:bd}

    def eulerNumber(self): 
        w1, w3, wd = self.quadsDicts[WHITE][Q1],self.quadsDicts[WHITE][Q3],self.quadsDicts[WHITE][Qd] 
        b1, b3, bd = self.quadsDicts[BLACK][Q1],self.quadsDicts[BLACK][Q3],self.quadsDicts[BLACK][Qd]           
        eWhite = (w1 - w3 - (2*wd))/4
        eBlack = (b1 - b3 - (2*bd))/4
        res = {}
        if eWhite == 0:
            res[WHITE]=0    
        else:
            res[WHITE]=1/float(eWhite)
        if eBlack == 0:
            res[BLACK]=0
        else:
            res[BLACK]=1/float(eBlack)
        return res
    
    def makeMove(self, newGameState, action):
#take note whether the move is of taking kind - if action captures an enemy unit or turns square
        checkEnemy = not(self.nWhites == newGameState.whites and 
                    self.nBlacks == newGameState.blacks) or isinstance(action, SpinAction)
        
        initRow, initCol = action.row, action.col #starting cell
        enemyColor = newGameState.getCurrentPlayer()
        if enemyColor == WHITE:
            color = BLACK
        else:
            color = WHITE
        
        
        oldq0, oldq1, oldq2, oldq3, oldq4, oldqd = 0,0,0,0,0,0
        newq0, newq1, newq2, newq3, newq4, newqd = 0,0,0,0,0,0
        
        if isinstance(action, SpinAction):
            #print "spin"
            beforeQuadList = getSquareNeighbourSquares(self.board, initRow, initCol)
            self.board = newGameState.board
            afterQuadList = getSquareNeighbourSquares(self.board,initRow, initCol)
        
        if isinstance(action, MoveAction):
#            destination cell
            deltaRow, deltaCol = action.direction.delta[DIR_ROW], action.direction.delta[DIR_COL]
            newRow, newCol = initRow + deltaRow, initCol + deltaCol
# quads around the starting and final locations before the move           
            initSquaresBefore = getCellSquares(self.board,initRow, initCol)
            endSquaresBefore = getCellSquares(self.board,newRow, newCol)
# quads around the starting and final locations after the move           
            self.board = newGameState.board
            initSquaresAfter = getCellSquares(self.board,initRow, initCol)
            endSquaresAfter  = getCellSquares(self.board,newRow, newCol)
# now iterate over both list and calculate for each quad type the change    
            beforeQuadList = initSquaresBefore + endSquaresBefore
            afterQuadList  = initSquaresAfter  + endSquaresAfter
            
        colors = [color]
        if (checkEnemy):
            colors.append(enemyColor)    
        #print colors
        for c in colors:
            oldq0, oldq1, oldq2, oldq3, oldq4, oldqd = 0,0,0,0,0,0
            newq0, newq1, newq2, newq3, newq4, newqd = 0,0,0,0,0,0    
            for i in range(0,len(beforeQuadList)):
                q = identifyQuad(beforeQuadList[i][0], beforeQuadList[i][1],
                    beforeQuadList[i][2], beforeQuadList[i][3], c)
                if q == Q0:
                    oldq0 = oldq0 + 1
                elif q == Q1:
                    oldq1 = oldq1 + 1
                elif q == Q2:
                    oldq2 = oldq2 + 1
                elif q == Q3:
                    oldq3 = oldq3 + 1
                elif q == Q4:
                    oldq4 = oldq4 + 1
                elif q == Qd:
                    oldqd = oldqd + 1
                    
                q = identifyQuad(afterQuadList[i][0], afterQuadList[i][1],
                    afterQuadList[i][2], afterQuadList[i][3], c)
                
                if q == Q0:
                    newq0 = newq0 + 1
                elif q == Q1:
                    newq1 = newq1 + 1
                elif q == Q2:
                    newq2 = newq2 + 1
                elif q == Q3:
                    newq3 = newq3 + 1
                elif q == Q4:
                    newq4 = newq4 + 1
                elif q == Qd:
                    newqd = newqd + 1
            #print oldq0, oldq1, oldq2, oldq3, oldq4, oldqd
            #print newq0, newq1, newq2, newq3, newq4, newqd                        
            self.quadsDicts[c][Q0] = self.quadsDicts[c][Q0] + newq0 - oldq0
            self.quadsDicts[c][Q1] = self.quadsDicts[c][Q1] + newq1 - oldq1
            self.quadsDicts[c][Q2] = self.quadsDicts[c][Q2] + newq2 - oldq2
            self.quadsDicts[c][Q3] = self.quadsDicts[c][Q3] + newq3 - oldq3
            self.quadsDicts[c][Q4] = self.quadsDicts[c][Q4] + newq4 - oldq4
            self.quadsDicts[c][Qd] = self.quadsDicts[c][Qd] + newqd - oldqd
            #print self.quadsDicts
        return